//头文件区
#include "bootloader_app2.h"
#include "main.h"
//变量区
uint32_t app1_fault_num = 0, app2_fault_num = 0;//APP启动失败次数
uint32_t app1_version = 0, app2_version = 0;//APP版本号


// Bootloader初始化函数
void Bootloader_Init(void)
{
		// 使用 volatile 关键字防止编译器优化掉内存访问
		// 使用 __IO 是 ST HAL 库中定义的标准写法，等同于 volatile
		app1_fault_num = *(__IO uint32_t*)(BOOT_PARAM_START_ADDRESS + 4 * BOOT_TO_APP1_FAULT);
		app2_fault_num = *(__IO uint32_t*)(BOOT_PARAM_START_ADDRESS + 4 * BOOT_TO_APP2_FAULT);

		app1_version = *(__IO uint32_t*)(BOOT_PARAM_START_ADDRESS + 4 * APP1_VERSION);
		app2_version = *(__IO uint32_t*)(BOOT_PARAM_START_ADDRESS + 4 * APP2_VERSION);
}

// Bootloader主流程函数，负责检查Bootloader标志并决定后续操作
void Bootloader_Run(void)
{
		app2_fault_num = 0;
		APP_Flash_Erase(BOOT_PARAM_SECTOR);
		APP_Flash_Write(BOOT_PARAM_START_ADDRESS + 4 * BOOT_TO_APP1_FAULT,(uint8_t *)&app1_fault_num,sizeof(app1_fault_num));
		APP_Flash_Write(BOOT_PARAM_START_ADDRESS + 4 * BOOT_TO_APP2_FAULT,(uint8_t *)&app2_fault_num,sizeof(app2_fault_num));
		APP_Flash_Write(BOOT_PARAM_START_ADDRESS + 4 * APP1_VERSION,(uint8_t *)&app1_version,sizeof(app1_version));
		APP_Flash_Write(BOOT_PARAM_START_ADDRESS + 4 * APP2_VERSION,(uint8_t *)&app2_version,sizeof(app2_version));
}

// 用于擦除应用程序所在Flash扇区的函数
// 参数Sector是要擦除的Flash扇区编号
void APP_Flash_Erase(uint32_t Sector)
{
    HAL_StatusTypeDef status;
    uint32_t pageError;

    FLASH_EraseInitTypeDef eraseInitStruct;

    // 设置擦除类型为按扇区擦除
    eraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
    // 指定要擦除的Flash存储体为银行1（Bank 1）
    eraseInitStruct.Banks = FLASH_BANK_1;
    // 将传入的参数Sector赋值给结构体成员，确定要擦除的具体扇区
    eraseInitStruct.Sector = Sector;
    // 表示此次擦除操作只针对1个扇区进行
    eraseInitStruct.NbSectors = 1;
    // 设置擦除操作对应的电压范围为3
    eraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;

    // 解锁Flash
    status = HAL_FLASH_Unlock();
    if (status!= HAL_OK)
    {
        LOG("Flash Unlock Error\r\n");
        return;
    }

    //执行Flash擦除操作
    status = HAL_FLASHEx_Erase(&eraseInitStruct, &pageError);
    if (status!= HAL_OK)
    {
        LOG("Flash Erase Error, pageError = %u\r\n",pageError);
        HAL_FLASH_Lock();
        return;
    }

    // 擦除操作完成后，锁定Flash
    HAL_FLASH_Lock();
}

// 用于向Flash中写入应用程序固件数据的函数
// 参数APP_FLAG_ADDRESS是要写入的起始地址，firmware_buffer是指向固件数据缓冲区的指针，firmware_size是固件数据的大小（字节数）
void APP_Flash_Write(uint32_t APP_FLAG_ADDRESS,uint8_t *firmware_buffer,uint32_t firmware_size)
{
    HAL_StatusTypeDef status;

    // 解锁Flash
    status = HAL_FLASH_Unlock();
    if (status!= HAL_OK)
    {
        LOG("Flash Unlock Error\r\n");
        return;
    }

    // 通过循环逐个字节地将固件数据写入Flash中
    for (uint32_t i = 0; i < firmware_size; i++)
    {
        // 调用HAL_FLASH_Program函数以字节为单位进行写入操作
        status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, APP_FLAG_ADDRESS + i, firmware_buffer[i]);
        if (status!= HAL_OK)
        {
            LOG("Flash Program Error at address 0x%X\r\n", APP_FLAG_ADDRESS + i);
            HAL_FLASH_Lock();
            return;
        }
    }

    // 所有字节数据写入完成后，锁定Flash，防止数据异常
    HAL_FLASH_Lock();
}

